package by.gamedev.site.client.app;

import java.util.logging.Level;
import java.util.logging.Logger;

import by.gamedev.site.client.app.place.GameDevPlaceHistoryMapper;
import by.gamedev.site.client.app.place.PlaceHistoryFactory;
import by.gamedev.site.client.app.place.ProxyPlaceToListPlace;
import by.gamedev.site.client.managed.activity.ApplicationMasterActivities;
import by.gamedev.site.client.managed.request.ApplicationRequestFactory;

import com.google.gwt.activity.shared.ActivityManager;
import com.google.gwt.activity.shared.ActivityMapper;
import com.google.gwt.activity.shared.CachingActivityMapper;
import com.google.gwt.activity.shared.FilteredActivityMapper;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.requestfactory.shared.RequestEvent;
import com.google.gwt.requestfactory.ui.client.AuthenticationFailureHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.inject.Inject;

/**
 * Application for browsing entities.
 */
public class GameDevDesktopApp extends GameDevApp {

    static final Logger                       log = Logger.getLogger(GameDev.class.getName());

    final GameDevDesktopShell                 shell;
//TODO    private final ApplicationRequestFactory   requestFactory;
    private final EventBus                    eventBus;
    private final PlaceController             placeController;
    private final PlaceHistoryFactory         placeHistoryFactory;
    private final ApplicationMasterActivities applicationMasterActivities;

    @Inject
    public GameDevDesktopApp(final GameDevDesktopShell shell, final ApplicationRequestFactory requestFactory, final EventBus eventBus,
            final PlaceController placeController, final PlaceHistoryFactory placeHistoryFactory,
            final ApplicationMasterActivities applicationMasterActivities) {
        this.shell = shell;
      //TODO        this.requestFactory = requestFactory;
        this.eventBus = eventBus;
        this.placeController = placeController;
        this.placeHistoryFactory = placeHistoryFactory;
        this.applicationMasterActivities = applicationMasterActivities;
    }

    @Override
    public void run() {

        /* Add handlers, setup activities */

        init();

        /* Hide the loading message */

        final Element loading = Document.get().getElementById("loading");
        loading.getParentElement().removeChild(loading);

        /* And show the user the shell */

        RootLayoutPanel.get().add(shell);

    }

    private void init() {

        GWT.setUncaughtExceptionHandler(new GWT.UncaughtExceptionHandler() {
            @Override
            public void onUncaughtException(final Throwable e) {
                Window.alert("Error: " + e.getMessage());
                log.log(Level.SEVERE, e.getMessage(), e);
            }
        });
//TODO
        /*
        final Receiver<UserInformationProxy> receiver = new Receiver<UserInformationProxy>() {
            @Override
            public void onSuccess(final UserInformationProxy userInformationProxy) {
                shell.getLoginWidget().setUserInformation(userInformationProxy);
            }
        };
        */
        // TODO requestFactory.userInformationRequest().getCurrentUserInformation(Window.Location.getHref()).fire(receiver);
        /*
         * if(LogConfiguration.loggingIsEnabled() ) { // Add remote logging handler final RequestFactoryLogHandler.LoggingRequestProvider provider =
         * new RequestFactoryLogHandler.LoggingRequestProvider() {
         * 
         * @Override public LoggingRequest getLoggingRequest() { return requestFactory.loggingRequest(); } }; Logger.getLogger("").addHandler(new
         * RequestFactoryLogHandler(provider, Level.WARNING, new ArrayList<String>())); }
         */
        RequestEvent.register(eventBus, new RequestEvent.Handler() {
            // Only show loading status if a request isn't serviced in 250ms.
            private static final int LOADING_TIMEOUT = 250;

            @Override
            public void onRequestEvent(final RequestEvent requestEvent) {
                if(requestEvent.getState() == RequestEvent.State.SENT ) {
                    shell.getMole().showDelayed(LOADING_TIMEOUT);
                } else {
                    shell.getMole().hide();
                }
            }
        });

        /* Check for Authentication failures or mismatches */

        RequestEvent.register(eventBus, new AuthenticationFailureHandler());

        final CachingActivityMapper cached = new CachingActivityMapper(applicationMasterActivities);
        final ProxyPlaceToListPlace proxyPlaceToListPlace = new ProxyPlaceToListPlace();
        final ActivityMapper masterActivityMap = new FilteredActivityMapper(proxyPlaceToListPlace, cached);
        final ActivityManager masterActivityManager = new ActivityManager(masterActivityMap, eventBus);

        masterActivityManager.setDisplay(shell.getMasterPanel());
/*
        final ProxyListPlacePicker proxyListPlacePicker = new ProxyListPlacePicker(placeController, proxyPlaceToListPlace);
        final HasConstrainedValue<ProxyListPlace> listPlacePickerView = shell.getPlacesBox();
        listPlacePickerView.setAcceptableValues(getTopPlaces());
        proxyListPlacePicker.register(eventBus, listPlacePickerView);
*/
        /* Browser history integration */
        final GameDevPlaceHistoryMapper mapper = GWT.create(GameDevPlaceHistoryMapper.class);
        mapper.setFactory(placeHistoryFactory);
//        final PlaceHistoryHandler placeHistoryHandler = new PlaceHistoryHandler(mapper);
//        final ProxyListPlace defaultPlace = getTopPlaces().iterator().next();
//        placeHistoryHandler.register(placeController, eventBus, defaultPlace);
//        placeHistoryHandler.handleCurrentHistory();
    }
}
